An enhanced XML-RPC client/server interface for Python.
"""
+import re
import string
import fcntl
from types import *
class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer):
allow_reuse_address = True
- def __init__(self, addr, allowed, requestHandler=None,
+ def __init__(self, addr, allowed, xenapi, requestHandler=None,
logRequests = 1):
+ self.xenapi = xenapi
+
if requestHandler is None:
requestHandler = XMLRPCRequestHandler
SimpleXMLRPCServer.__init__(self, addr,
flags |= fcntl.FD_CLOEXEC
fcntl.fcntl(client.fileno(), fcntl.F_SETFD, flags)
return (client, addr)
-
+
def _marshaled_dispatch(self, data, dispatch_method = None):
params, method = xmlrpclib.loads(data)
if False:
except xmlrpclib.Fault, fault:
response = xmlrpclib.dumps(fault)
except Exception, exn:
- import xen.xend.XendClient
- log.exception(exn)
- response = xmlrpclib.dumps(
- xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn)))
-
+ if self.xenapi:
+ if _is_not_supported(exn):
+ errdesc = ['MESSAGE_METHOD_UNKNOWN', method]
+ else:
+ log.exception('Internal error handling %s', method)
+ errdesc = ['INTERNAL_ERROR', str(exn)]
+ response = xmlrpclib.dumps(
+ ({ "Status": "Failure",
+ "ErrorDescription": errdesc },),
+ methodresponse = 1)
+ else:
+ log.exception('Internal error handling %s', method)
+ import xen.xend.XendClient
+ response = xmlrpclib.dumps(
+ xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn)))
return response
+
+notSupportedRE = re.compile(r'method "(.*)" is not supported')
+def _is_not_supported(exn):
+ m = notSupportedRE.search(exn[0])
+ return m is not None
+
+
# This is a XML-RPC server that sits on a Unix domain socket.
# It implements proper support for allow_reuse_address by
# unlink()'ing an existing socket.
class UnixXMLRPCServer(TCPXMLRPCServer):
address_family = socket.AF_UNIX
- def __init__(self, addr, allowed, logRequests = 1):
+ def __init__(self, addr, allowed, xenapi, logRequests = 1):
mkdir.parents(os.path.dirname(addr), stat.S_IRWXU, True)
if self.allow_reuse_address and os.path.exists(addr):
os.unlink(addr)
- TCPXMLRPCServer.__init__(self, addr, allowed,
+ TCPXMLRPCServer.__init__(self, addr, allowed, xenapi,
UnixXMLRPCRequestHandler, logRequests)
if len(addrport) == 1:
if addrport[0] == 'unix':
- servers.add(XMLRPCServer(auth,
+ servers.add(XMLRPCServer(auth, True,
path = XEN_API_SOCKET,
hosts_allowed = allowed))
else:
servers.add(
- XMLRPCServer(auth, True, '', int(addrport[0]),
+ XMLRPCServer(auth, True, True, '',
+ int(addrport[0]),
hosts_allowed = allowed))
else:
addr, port = addrport
- servers.add(XMLRPCServer(auth, True, addr, int(port),
+ servers.add(XMLRPCServer(auth, True, True, addr,
+ int(port),
hosts_allowed = allowed))
except ValueError, exn:
log.error('Xen-API server configuration %s is invalid.', api_cfg)
log.error('Xen-API server configuration %s is invalid.', api_cfg)
if xroot.get_xend_tcp_xmlrpc_server():
- servers.add(XMLRPCServer(XendAPI.AUTH_PAM, True))
+ servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, True))
if xroot.get_xend_unix_xmlrpc_server():
- servers.add(XMLRPCServer(XendAPI.AUTH_PAM))
+ servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False))
def create():
exclude = ['domain_create', 'domain_restore']
class XMLRPCServer:
- def __init__(self, auth, use_tcp=False, host = "localhost", port = 8006,
- path = XML_RPC_SOCKET, hosts_allowed = None):
+ def __init__(self, auth, use_xenapi, use_tcp=False, host = "localhost",
+ port = 8006, path = XML_RPC_SOCKET, hosts_allowed = None):
self.use_tcp = use_tcp
self.port = port
self.host = host
self.ready = False
self.running = True
self.auth = auth
- self.xenapi = XendAPI.XendAPI(auth)
+ self.xenapi = use_xenapi and XendAPI.XendAPI(auth) or None
def run(self):
authmsg = (self.auth == XendAPI.AUTH_NONE and
self.port, authmsg)
self.server = TCPXMLRPCServer((self.host, self.port),
self.hosts_allowed,
+ self.xenapi is not None,
logRequests = False)
else:
log.info("Opening Unix domain socket XML-RPC server on %s%s",
self.path, authmsg)
self.server = UnixXMLRPCServer(self.path, self.hosts_allowed,
+ self.xenapi is not None,
logRequests = False)
except socket.error, exn:
log.error('Cannot start server: %s!', exn.args[1])
# and has the 'api' attribute.
for meth_name in dir(self.xenapi):
- meth = getattr(self.xenapi, meth_name)
- if meth_name[0] != '_' and callable(meth) and hasattr(meth, 'api'):
- self.server.register_function(meth, getattr(meth, 'api'))
+ if meth_name[0] != '_':
+ meth = getattr(self.xenapi, meth_name)
+ if callable(meth) and hasattr(meth, 'api'):
+ self.server.register_function(meth, getattr(meth, 'api'))
# Legacy deprecated xm xmlrpc api
# --------------------------------------------------------------------